/*
 * SocketManager.cpp
 *
 *  Created on: May 8, 2011
 *      Author: michael
 */

#include "../StdAfx.h"
#include "SocketManager.h"
#include "RawData.h"
#include "TcpServer.h"
#include "../Messages/Hello.pb.h"
#include "../Messages/MessageTypes.pb.h"
#include "TcpConnection.h"
#include "../MainManager.h"
#include <boost/bind.hpp>
#include <limits>

namespace DerbyServ
{

SocketManager::SocketManager()
{
	messageProcessors = RegisterMessageProcessors();
}

SocketManager::~SocketManager()
{
	// TODO Auto-generated destructor stub
}

void SocketManager::Start()
{
	BOOST_ASSERT(_tcpServer.get() == 0);
	_tcpServer.reset(new TcpServer(_ioService)); //it is a scoped_ptr
}

void SocketManager::Send(const google::protobuf::MessageLite & message, enum Messages::MessageTypes type, int connectionId)
{
	RawData rawData(message, type);
	_tcpServer->Send(rawData, connectionId);
}

void SocketManager::ReadAll(MainManager & mgr)
{
	//LOG_SCOPE;
	_ioService.poll();
	_ioService.reset();

	TcpServer::ConnectionIds keys = _tcpServer->GetConnectionIds();
	for(TcpServer::ConnectionIds::const_iterator it = keys.begin()
			; it != keys.end(); ++it)
	{
		TcpServer::ConnectionIds::value_type cId = *it;
		RawData raw;
		if (_tcpServer->Receive(raw, cId))
		{
			LOGD("Received a message from the client #" << cId);
			ProcessRawData(mgr, raw, cId);
		}
		else
		{
			continue;
		}
	}
}

void SocketManager::ProcessRawData(MainManager & mgr, RawData & raw, int connectionId)
{
	LOGD("Looking for a message processor for the type #" << raw.Type());
	std::map<enum Messages::MessageTypes, ProcessMessage>::const_iterator processItertator = messageProcessors.find(raw.Type());
	BOOST_ASSERT(processItertator != messageProcessors.end());
	if (processItertator != messageProcessors.end())
	{
		(processItertator->second)(mgr, raw.Data(), connectionId);
	}
	else
	{
		LOGE("Failed to find a message processor for the type " << raw.Type());
	}
}

TcpServer::ConnectionIds SocketManager::GetConnectionIds() const {
	return _tcpServer->GetConnectionIds();
}


} //namespace
